package controllers;

import gui.WelcomeUI;

import java.io.IOException;


import java.util.Observable;
import java.util.Observer;
// Needed to check if IP is valid
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import javax.swing.JOptionPane;

import ocsf.client.ObservableSWRClient;
import messagesPacks.*;

/**
 * This class represents the common operation for users on the OBL system.
 * @author Alon Shahaf
 * @author Ariel Brucker
 * @author Tali Pisarev
 * @author Roman Faktorovich
 * @Date 11.12.2013
 */	



public class WelcomeUIP implements Observer
{
	static ChatClient client;
	int userPermission = 0 ; /* Permission :
	 										 1 - librarian Manager 
	 										 2 - librarian 
	 										 3 - subscriber Reader
	 										 4 - Administrator
	 										 5 - subscriber Reader suspended
	 														*/
	
	/**
	 * Creates a new connection.
	 */
	public WelcomeUIP() 
	{
		System.out.println("WelcomeUIP created.");
	    client = new ChatClient();
	    client.addObserver(this);
	}
	
	
	/**
	   * This method handles the connection to the server.
	   *
	   * @param ip , port.
	   */
	public boolean connect(String ip,String port)
	{
		int portnum;
		// Check port
		try
		{
			portnum=Integer.parseInt(port);
		}
		catch (NullPointerException e)
		{
			return false;
		}
		catch (NumberFormatException e)
		{
			return false;
		}
		if ((ip.isEmpty()) || (port.isEmpty())) 
			return false;
		if ((portnum < 1024) || (portnum > 65535)) 
			return false;
		// Check IP 
		if ( validateIP(ip) == false ) 
			return false;
		
		// Start connection to server
	    try 
	    {
	    	client.startConnection(ip,portnum);
	    } 
	    catch(IOException exception) 
	    {  
	    	return false;
	    }
		return true;
	}
	

	/**
	   * This method performs the login for the user.
	   * @param :userName , password.
	   * @return: -1 error			
	   *  			>0 the user permission
	   */
	public LoginMessage login(String user,String pass)
	{
		// Create the login message
		LoginMessage login_msg = new LoginMessage(user,pass);
		
		try 
		{
			System.out.println("Sending LOGIN & WAITING..");
			client.setMaxRetries(2);
			client.setWaitTime(3000);
			Object return_obj = null;
			return_obj = client.sendToServerAndWait(login_msg, login_msg);
			
			if (return_obj==null)
			{
				// Timeout OR error in transmit.
				System.out.println("UIP: (NULL) login result=-1");
				return null;
			}
			else
			{
				System.out.println("WelcomeUIP: login result = " + ((LoginMessage)return_obj).getLoginResult());
				return (LoginMessage)return_obj;
			}
		} 
		catch (Exception e) 
		{
			System.out.println("UIP: EXCEPTION in login ");
			e.printStackTrace();
			return null;
		}
	}
	
	/**
	 * Logs out from the server.
	@return 1 for success, -1 otherwise
	 */
	public int logout()
	{
		try 
	    {
			LogoutMessage logout_msg = new LogoutMessage(client.getInetAddress().getHostAddress());
			// Send the server logout message
			System.out.println("Sending LOGOUT & WAITING..");
			client.setMaxRetries(2);
			client.setWaitTime(3000);
			Object return_obj=null;
			return_obj = client.sendToServerAndWait(logout_msg, logout_msg);
			
			if (return_obj==null)
			{
				// Timeout OR error in transmit.
				System.out.println("UIP: (logout) logout result=-1");
				return -1;
			}
			else
			{
				System.out.println("WelcomeUIP: (logout) logout result = " + ((LogoutMessage)return_obj).getLogoutResult());
				if (((LogoutMessage)return_obj).getLogoutResult() == 1)
					return 1;
			}
	    }
		catch (NullPointerException e)
		{	
			System.out.println("UIP@Client: (logout) error closing connection.");
		}
		return -1;
	}
	

	/**
	 * Checks an IP address to see if it's valid.
	 * @param ip	The IP to check.
	 * @return true if valid, false otherwise.
	 */
	protected static boolean validateIP(String ip) 
	 {
	     if (ip == null || ip.isEmpty()) return false;
	     if (ip.equals("localhost")) return true;
	     ip = ip.trim();
	     if ((ip.length() < 6) & (ip.length() > 15)) return false;

	     try 
	     {
	         Pattern pattern = Pattern.compile("^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$");
	         Matcher matcher = pattern.matcher(ip);
	         return matcher.matches();
	     }
	     catch (PatternSyntaxException ex) 
	     {
	         return false;
	     }
	 }
	
   /** 
	 * @author Roman&Tali 
	 * 
	 * this method is for closing the connection and exiting the client side
	 */
	public void Exit(WelcomeUI welcomeFrame)
	{
		if (JOptionPane.showConfirmDialog(welcomeFrame,"Are you sure?", "Quitting",JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION)
		{
			try 
		    {
				if ((client.isConnected()))
				{
					client.closeConnection();
					System.out.println("UIP@Client: connection closed.");
				} 
		    }
			catch (IOException e) 
			{
					e.printStackTrace();
			}
			catch (NullPointerException e)
			{	
				System.out.println("UIP@Client: EXIT event.");
				System.exit(0);
			}
		  System.out.println("UIP@Client: EXIT event.");
		  System.exit(0);
		}
	}
	
	@Override
	public void update(Observable arg0, Object arg1) 
	{
		System.out.println("UIP: Recieved notify: arg0:   " + arg0.toString() + "   |   arg1: "+ arg1.toString());
		if (arg1 == ObservableSWRClient.CONNECTION_CLOSED)
		{
			System.out.printf("UIP: Connection closed notify.");
			if (client.isConnected())
			{
				System.out.printf("Closing connection..");
				try 
				{
					client.closeConnection();
				} 
				catch (IOException e) {}
			}
		}
		
		if (arg1 == ObservableSWRClient.WAITING_FOR_REPLY) 
		{
			if (client.getWaitRetries() == client.getMaxRetries())
			{
				System.out.println("Canceling operation with server.");
				client.cancel();
				client.setWaitRetries(0);
			}
		}
	}
	
	public ChatClient getClient()
	{
		return client;
	}
	
	
	

//=========================================================================================================
	
	
	
	
}//class